home *** CD-ROM | disk | FTP | other *** search
/ BCI NET / BCI NET Dec 94.iso / archives / programming / source / yak160src.lha / Yak_1.60_Src / handler.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-09-28  |  18.2 KB  |  581 lines

  1.  
  2. /*
  3.  * handler.c
  4.  *
  5.  * Routines to set up handler.
  6.  * Part of Yak.
  7.  *
  8.  * Martin W. Scott, 9/92.
  9.  */
  10. #include <exec/types.h>
  11. #include <exec/exec.h>
  12. #include <hardware/custom.h>
  13. #include <hardware/dmabits.h>
  14. #include <devices/console.h>
  15. #include <devices/input.h>
  16. #include <devices/inputevent.h>
  17. #include <libraries/commodities.h>
  18. #include <graphics/gfxbase.h>
  19. #include <graphics/gfxmacros.h>
  20. #include <graphics/displayinfo.h>
  21. #include <intuition/intuition.h>
  22. #include <intuition/intuitionbase.h>
  23. #include <proto/exec.h>
  24. #include <proto/dos.h>
  25. #include <proto/layers.h>
  26. #include <proto/graphics.h>
  27. #include <proto/intuition.h>
  28. #include <proto/commodities.h>
  29. #include <string.h>
  30. #include <stdio.h>
  31.  
  32. #include "code.h"
  33. #include "yak.h"
  34. #include "beep.h"
  35.  
  36. void TurnMouseOn (void);
  37. static void TurnMouseOff (void);
  38. static __regargs void IntuiOp (void (*routine) (APTR), APTR parameter);
  39. static __regargs void PopToFront (struct Window *win);
  40. static struct Window *WindowUnderMouse (void);
  41. static __regargs BOOL StrGadgetActive (struct Window *w);
  42.  
  43. extern __far struct Custom custom;
  44.  
  45. #define REBLANKCOUNT    10      /* how long to wait to reblank mouse */
  46.  
  47. void (*intui_routine) (APTR);   /* for intui_op's */
  48. APTR intui_parameter;
  49. CxObj *clickobj;
  50. ULONG clicksigflag, intuiopsigflag, blankscreensigflag;
  51. static BYTE clicksigbit, blankscreensigbit, intuiopsigbit = -1;
  52. static struct Task *thistask;
  53. static BOOL misspop;
  54.  
  55.  
  56. /* for screen click-to-back */
  57. STACKARGS void
  58.     MyScreenToBack (struct Screen *scr)
  59. {
  60.     RememberActiveWindow();
  61.     ScreenToBack (scr);
  62.     ActivateMouseWindow (SCREEN);
  63. }
  64.  
  65.  
  66. /* Stub for Intuition routines - passes request on to main task.
  67.  * DO NOT CALL WHILE FORBID()ING!
  68.  
  69.  * Thanks to Eddy Carroll for this.
  70.  */
  71.  
  72. #define WTB(win)        IntuiOp(WindowToBack, win)
  73. #define WTF(win)        IntuiOp(WindowToFront, win)
  74. #define WACT(win)       IntuiOp((void (*)(APTR))ActivateWindow, win)
  75. #define STB(scr)        IntuiOp(MyScreenToBack, scr)
  76. #define STF(scr)        IntuiOp(ScreenToFront, scr)
  77.  
  78. static __regargs void
  79.     IntuiOp (void (*routine) (APTR), APTR parameter)
  80. {
  81.     BYTE oldpri = SetTaskPri (thistask, 21);
  82.     
  83.     intui_routine = routine;
  84.     intui_parameter = parameter;
  85.     Signal (thistask, intuiopsigflag);
  86.     SetTaskPri (thistask, oldpri);
  87. }
  88.  
  89. /* pattern-matching on screen/window titles */
  90. #define IsXXXScreen(scr, pat)  (scr && (!scr->DefaultTitle || MatchPattern(pat, scr->DefaultTitle)))
  91. #define IsClickScreen(scr)         IsXXXScreen(scr, clickscrpat)
  92. #define IsAutoScreen(scr)          IsXXXScreen(scr, autoscrpat)
  93. #define IsXXXWindow(win, pat)  (!win->Title || MatchPattern(pat, win->Title))
  94. #define IsPopWindow(win)           IsXXXWindow(win,popwinpat)
  95. #define IsClickWindow(win)         IsXXXWindow(win,clickwinpat)
  96.  
  97.  
  98. /* when is a window safe to bring to front and not already at front? */
  99. #define OkayToPop(win)  (!win->ReqCount && !(win->Flags & (WFLG_MENUSTATE|WFLG_BACKDROP)) \
  100.                          && win->WLayer->ClipRect && win->WLayer->ClipRect->Next)
  101.  
  102.  
  103. /* WindowToFront only if no requester, not backdrop, not already front... */
  104. static __regargs void
  105.     PopToFront (struct Window *win)
  106. {
  107.     /* want to avoid popping immediately after mousebutton/keyboard */
  108.     if (misspop)
  109.         misspop = FALSE;
  110.     else if (OkayToPop (win))
  111.     {
  112.         /* Does it pass pattern? */
  113.         if (IsPopWindow (win))
  114.             WTF (win);
  115.     }
  116. }
  117.  
  118. /* modified from DMouse */
  119. /* expects multitasking to be Forbid()en */
  120.  
  121. static struct Screen *mousescr; /* the screen under the mouse */
  122.  
  123.  
  124. struct Screen
  125.     *ScreenUnderMouse( void )
  126. {
  127.     struct Screen *scr;
  128.     ULONG lock;
  129.     
  130.     lock = LockIBase(0);
  131.     
  132.     for (scr = FS;
  133.          (scr && scr->TopEdge > 0) && (scr->MouseY < 0); 
  134.          scr = scr->NextScreen);
  135.     
  136.     UnlockIBase(lock);
  137.     
  138.     return(scr);
  139. }
  140.  
  141.  
  142. static struct Window 
  143.     *WindowUnderMouse( void )
  144. {
  145.     struct Layer *layer = NULL;
  146.     ULONG lock;
  147.     
  148.     lock = LockIBase(0);
  149.     
  150.     for (mousescr = FS;
  151.          mousescr && (mousescr->TopEdge > 0) && (mousescr->MouseY < 0); 
  152.          mousescr = mousescr->NextScreen);
  153.     
  154.     UnlockIBase(lock);
  155.     
  156.     if (mousescr)
  157.         layer = WhichLayer(&mousescr->LayerInfo, mousescr->MouseX, mousescr->MouseY);
  158.     
  159.     return (layer ? (struct Window *) layer->Window : NULL);
  160. }
  161.  
  162.  
  163. /* does active window have an active string gadget? */
  164. static __regargs BOOL
  165.     StrGadgetActive (struct Window *w)
  166. {
  167.     struct Gadget *g = w->FirstGadget;
  168.     
  169.     for (; g; g = g->NextGadget)
  170.         if ((g->GadgetType & STRGADGET) && (g->Flags & GFLG_SELECTED))
  171.             return TRUE;
  172.     return FALSE;
  173. }
  174.  
  175. /* activate window under mouse */
  176. /* context sensitive; why tells routine how to behave */
  177. /* can be AUTO, KEY, SCREEN, RMBACT */
  178. __regargs void
  179.     ActivateMouseWindow (BYTE why)
  180. {
  181.     struct Window *win = NULL, *IB_ActiveWindow;
  182.     ULONG lock;
  183.     
  184.     if ((why != SCREEN) || scractivate)
  185.     {
  186.         if (why == SCREEN)
  187.             win = LastActiveWindow(ScreenUnderMouse());
  188.         
  189.         if (!win)
  190.             win = WindowUnderMouse ();
  191.         
  192.         
  193.         if (win) /* window exists to activate */
  194.         {
  195.             /* either window is not active or auto-activating - need to pop? */
  196.             
  197.             if (win->Flags & WFLG_WINDOWACTIVE) /* already active - needs popped? */
  198.             {
  199.                 if (why == AUTO && autopop && IsAutoScreen (win->WScreen))
  200.                 {
  201.                     PopToFront (win);
  202.                 }
  203.             }
  204.             else if (why != AUTO || IsAutoScreen (win->WScreen))
  205.             {
  206.                 /* window is not active, should we try to activate it? */
  207.                 
  208.                 lock = LockIBase(0);
  209.                 IB_ActiveWindow = AW;   /* AW is IntuitionBase->ActiveWindow */
  210.                 UnlockIBase(lock);
  211.                 
  212.                 if (!IB_ActiveWindow ||
  213.                     !(IB_ActiveWindow->Flags & WFLG_MENUSTATE) && /* not showing menus */
  214.                     !(why == KEY && StrGadgetActive (IB_ActiveWindow))) /* no str gad active */
  215.                 {
  216.                     
  217.                     /* do autopop? */
  218.                     if (why == AUTO && autopop)
  219.                         PopToFront (win);
  220.                     
  221.                     if (why == KEY)
  222.                         ActivateWindow (win); /* need this to avoid losing keys */
  223.                     else
  224.                         WACT (win); /* ...activate window */
  225.                 }
  226.             }
  227.         }
  228.         else
  229.         {
  230.             lock = LockIBase(0);
  231.             IB_ActiveWindow = AW;   /* AW is IntuitionBase->ActiveWindow */
  232.             UnlockIBase(lock);
  233.             
  234.             if (scractivate && mousescr && mousescr->FirstWindow &&
  235.                 ((why == SCREEN) || 
  236.                  (why == RMBACT && IB_ActiveWindow && IB_ActiveWindow->WScreen != mousescr)))
  237.             {
  238.                 WACT (mousescr->FirstWindow); /* ...activate window */
  239.             }
  240.         }
  241.     }
  242. }
  243.  
  244. static __chip UWORD posctldata[4];
  245. static struct SimpleSprite simplesprite =
  246. {posctldata, 0, 0, 0, 0};
  247. static BOOL mouseoff;           /* is mouse off? (MB_SPRITES only) */
  248.  
  249. void 
  250.     TurnMouseOn ()                  /* restore mouse-pointer */
  251. {
  252.     if (mouseblank == MB_SPRITES) /* really dirty blanking */
  253.     {                           /* but guaranteed to work... */
  254.         if (mouseoff)
  255.         {
  256.             Forbid ();
  257.             WaitTOF ();
  258.             ON_SPRITE;
  259.             Permit ();
  260.         }
  261.     }
  262.     else
  263.     {
  264.         RethinkDisplay();
  265.     }
  266.     mouseoff = FALSE;
  267. }
  268.  
  269. static void 
  270.     TurnMouseOff ()                 /* blank mouse-pointer */
  271. {
  272.     if (!mouseoff)              /* no point in turning it off twice... */
  273.     {
  274.         Forbid ();
  275.         
  276.         if (mouseblank == MB_SPRITES)
  277.         {
  278.             WaitTOF ();
  279.             OFF_SPRITE;
  280.             custom.spr[0].dataa = custom.spr[0].datab = 0;          }
  281.         else
  282.         {
  283.             ChangeSprite(NULL, &simplesprite, (APTR)posctldata);
  284.         }
  285.         
  286.         Permit ();
  287.         
  288.         mouseoff = TRUE;
  289.     }
  290. }
  291.  
  292. static BOOL blanked;
  293. static struct Screen *blankscr;
  294.  
  295. /* blank display, by putting up a black screen */
  296. /* this screen's displaymode is cloned from front screen */
  297. void
  298.     BlankScreen (void)
  299. {
  300.     ULONG modeid = INVALID_ID;
  301.     
  302.     if (blankscr)
  303.         ScreenToFront (blankscr);
  304.     else
  305.     {
  306.         Forbid ();
  307.         if (FS)
  308.             modeid = GetVPModeID (&(FS->ViewPort));
  309.         Permit ();
  310.         if (modeid == INVALID_ID)
  311.             modeid = LORES_KEY;
  312.         
  313.         if (blankscr = OpenScreenTags (NULL, SA_Depth, 1,
  314.                                        SA_Title, "Yak blanking screen",
  315.                                        SA_Quiet, TRUE,
  316.                                        SA_Behind, TRUE,
  317.                                        SA_DisplayID, modeid,
  318.                                        TAG_DONE))
  319.         {
  320.             SetRGB4 (&blankscr->ViewPort, 0, 0, 0, 0);
  321.             ScreenToFront (blankscr);
  322.             blanked = TRUE;
  323.         }
  324.     }
  325.     OFF_SPRITE;
  326.     custom.spr[0].dataa = custom.spr[0].datab = 0;
  327. }
  328.  
  329. /* unblank display, i.e. close our screen */
  330. void
  331.     UnBlankScreen ()
  332. {
  333.     if (blankscr)
  334.         CloseScreen (blankscr);
  335.     blankscr = NULL;
  336.     blanked = FALSE;
  337.     ON_SPRITE;
  338. }
  339.  
  340. #define ALL_BUTTONS     (IEQUALIFIER_LEFTBUTTON|IEQUALIFIER_RBUTTON|IEQUALIFIER_MIDBUTTON)
  341. #define KEY_QUAL        (IEQUALIFIER_LSHIFT|IEQUALIFIER_RSHIFT \
  342.                          |IEQUALIFIER_CONTROL \
  343.                          |IEQUALIFIER_LALT|IEQUALIFIER_RALT \
  344.                          |IEQUALIFIER_LCOMMAND|IEQUALIFIER_RCOMMAND)
  345. #define ALL_QUALS       (ALL_BUTTONS|KEY_QUAL)
  346.  
  347. /* the input handler itself */
  348. SAVEDS void
  349.     Handler (CxMsg * CxMsg, CxObj * CO)
  350. {
  351.     static struct timeval lastclick; /* last left-button click */
  352.     static WORD apcount;        /* timer events since last mousemove */
  353.     struct InputEvent *ev;
  354.     struct Window *win;  
  355.     
  356.     ev = (struct InputEvent *) CxMsgData (CxMsg);
  357.     
  358.     if (ev->ie_Class == IECLASS_TIMER)
  359.     {
  360.         /*** AUTO-ACTIVATE/POP, SCREENBLANK, MOUSEBLANK ***/
  361.         if (!(ev->ie_Qualifier & ALL_QUALS) && autopoint && !apcount--)
  362.         {
  363.             ActivateMouseWindow (AUTO);
  364.         }
  365.         
  366.         if (blanktimeout && !--blankcount) /* blank screen? */
  367.         {
  368.             /* Don't blank screen while we are still in the input.device processing */
  369.             /* Take care of screen mode promotors that open requesters */
  370.             Signal (thistask, blankscreensigflag);
  371.             blankcount = blanktimeout; /* reset counter */
  372.         }                       /* in case screen opens on top */
  373.         
  374.         if (mouseblank && !--mblankcount) /* blank mouse? */
  375.         {
  376.             mouseoff = FALSE;   /* force reblank */
  377.             TurnMouseOff ();
  378.             /* in case someone else turns it on, reset counter */
  379.             mblankcount = REBLANKCOUNT;
  380.         }
  381.     }
  382.     else            
  383.     {
  384.         if ((ev->ie_Class == IECLASS_RAWKEY) && !(ev->ie_Code & IECODE_UP_PREFIX))
  385.         {
  386.             /*** MOUSEBLANK, KEYACTIVATE, KEYCLICK ***/
  387.             
  388.             blankcount = blanktimeout; /* reset blanking countdown */
  389.             if (blanked)        /* turn off screen-blanking */
  390.                 UnBlankScreen ();
  391.             
  392.             if (mouseblank)
  393.                 if (ev->ie_Qualifier & (IEQUALIFIER_LCOMMAND | IEQUALIFIER_RCOMMAND))
  394.                 {
  395.                     /* this allows use of keyboard to move mouse and to access menus */
  396.                     mblankcount = mblanktimeout;
  397.                     TurnMouseOn ();
  398.                 }
  399.                 else
  400.                 {
  401.                     if (blankmouseonkey)
  402.                     {
  403.                         TurnMouseOff (); /* blank the mouse */
  404.                     }
  405.                 }
  406.             if (click_volume)
  407.                 Signal (thistask, clicksigflag);
  408.             
  409.             if (keyactivate)    /* perform key-activate */
  410.                 ActivateMouseWindow (KEY);
  411.         }
  412.         else if (ev->ie_Class == IECLASS_RAWMOUSE)
  413.         {
  414.             /*** CLICKTOFRONT/BACK, AUTOACTIVATE ***/
  415.             
  416.             /* restore screen/mouse pointer */
  417.             blankcount = blanktimeout; /* reset blanking countdowns */
  418.             mblankcount = mblanktimeout;
  419.             if (blanked)        /* turn off screen-blanking */
  420.                 UnBlankScreen ();
  421.             if (mouseoff)
  422.                 TurnMouseOn (); /* not needed for MB_COPPER */
  423.             
  424.             /* window/screen cycling... */
  425.             /* maybe should check for depth gadgets? nah... */
  426.             if (!(ev->ie_Qualifier & KEY_QUAL))
  427.             {
  428.                 if (!(ev->ie_Qualifier & ALL_BUTTONS))
  429.                 {
  430.                     apcount = autopoint_delay; /* reset auto-activate count */
  431.                 }
  432.                 else
  433.                     /* a button - check out clicktofront etc. */
  434.                 {
  435.                     misspop = TRUE;
  436.                     apcount = -1; /* button - wait for move */
  437.                     
  438.                     if (clicktofront && ev->ie_Code == IECODE_LBUTTON)
  439.                     {
  440.                         if (DoubleClick (lastclick.tv_secs,
  441.                                          lastclick.tv_micro,
  442.                                          ev->ie_TimeStamp.tv_secs,
  443.                                          ev->ie_TimeStamp.tv_micro))
  444.                         {
  445.                             win = WindowUnderMouse ();
  446.                             
  447.                             if (win)
  448.                             {
  449.                                 mousescr = win->WScreen;
  450.                                 
  451.                                 if (IsClickScreen ( mousescr ))
  452.                                 {
  453.                                     if (!(win->Flags & WFLG_BACKDROP) 
  454.                                         && IsClickWindow (win) && OkayToPop (win))
  455.                                     {
  456.                                         WTF (win); 
  457.                                     }
  458.                                     else 
  459.                                         if (screencycle)
  460.                                         {   
  461.                                             RememberActiveWindow();
  462.                                             STF (mousescr); 
  463.                                         }
  464.                                 }
  465.                             }
  466.                             else 
  467.                             {
  468.                                 mousescr = ScreenUnderMouse();
  469.                                 if (IsClickScreen ( mousescr ) && screencycle)
  470.                                 {
  471.                                     RememberActiveWindow();
  472.                                     STF (mousescr);
  473.                                 }
  474.                             }
  475.                             lastclick.tv_secs = 0;
  476.                             lastclick.tv_micro = 0;
  477.                         }
  478.                         else
  479.                         {
  480.                             lastclick.tv_secs = ev->ie_TimeStamp.tv_secs;
  481.                             lastclick.tv_micro = ev->ie_TimeStamp.tv_micro;
  482.                         }
  483.                     }
  484.                     else 
  485.                     {
  486.                         if (ev->ie_Code == IECODE_RBUTTON && 
  487.                             (ev->ie_Qualifier & IEQUALIFIER_LEFTBUTTON) &&
  488.                             clicktoback)
  489.                         {
  490.                             win = WindowUnderMouse ();
  491.                             
  492.                             if (win)
  493.                             {
  494.                                 mousescr = win->WScreen;
  495.                                 if (IsClickScreen ( mousescr ))
  496.                                 {
  497.                                     if (!(win->Flags & WFLG_BACKDROP) 
  498.                                         && (win->NextWindow || win->WScreen->FirstWindow != win))
  499.                                     {
  500.                                         WTB(win); 
  501.                                     }
  502.                                     else 
  503.                                         if (screencycle)
  504.                                         {
  505.                                             STB (mousescr); 
  506.                                         }
  507.                                 }       
  508.                             }
  509.                             else 
  510.                             {
  511.                                 mousescr = ScreenUnderMouse();
  512.                                 if (IsClickScreen ( mousescr ) && screencycle)
  513.                                 {
  514.                                     ev->ie_Class = IECLASS_NULL;
  515.                                     STB (mousescr);
  516.                                 }
  517.                             }
  518.                         }
  519.                         else
  520.                         { 
  521.                             if ((rmbactivate && (ev->ie_Code == IECODE_RBUTTON)) || 
  522.                                 (mmbactivate && (ev->ie_Code == IECODE_MBUTTON)))
  523.                             {
  524.                                 ActivateMouseWindow (RMBACT);
  525.                             }
  526.                         }
  527.                     }
  528.                 }
  529.             }
  530.         }
  531.         else 
  532.         {
  533.             if (ev->ie_Class == IECLASS_DISKINSERTED)
  534.             {
  535.                 blankcount = blanktimeout; /* reset blanking countdown */
  536.                 if (blanked)    /* turn off screen-blanking */
  537.                     UnBlankScreen ();
  538.             }
  539.         }
  540.     }
  541. }
  542.  
  543. /* close resources allocated for handler */
  544. void
  545.     EndHandler ()
  546. {
  547.     if (clickobj)
  548.         DeleteCxObj (clickobj);
  549.     FreeAudio ();
  550.     if (intuiopsigbit != -1)
  551.         FreeSignal (intuiopsigbit);
  552.     if (clicksigbit != -1)
  553.         FreeSignal (clicksigbit);
  554.     if (blankscreensigbit != -1)
  555.         FreeSignal (blankscreensigbit);
  556.     UnBlankScreen ();
  557. }
  558.  
  559. /* open resources needed for handler */
  560. BOOL
  561.     InitHandler ()
  562. {
  563.     if (((clicksigbit = AllocSignal (-1)) != -1) &&
  564.         ((intuiopsigbit = AllocSignal (-1)) != -1) &&
  565.         ((blankscreensigbit = AllocSignal (-1)) != -1) &&
  566.         AllocAudio ())
  567.     {
  568.         thistask = FindTask (NULL);       /* initialize liason structure */
  569.         clicksigflag = 1 << clicksigbit;
  570.         intuiopsigflag = 1 << intuiopsigbit;
  571.         blankscreensigflag = 1 << blankscreensigbit;
  572.         
  573.         clickobj = CxCustom (Handler, 0L);
  574.         AttachCxObj (broker, clickobj);
  575.         return TRUE;
  576.     }
  577.     EndHandler ();
  578.     return FALSE;
  579. }
  580.  
  581.